package xyz.lwm.lazycat.ds;

import lombok.extern.slf4j.Slf4j;
import xyz.lwm.lazycat.annotation.Bean;
import xyz.lwm.lazycat.annotation.ConditionalOnMissingBean;
import xyz.lwm.lazycat.annotation.Configuration;
import xyz.lwm.lazycat.annotation.Inject;
import xyz.lwm.lazycat.annotation.SettingPrefix;
import xyz.lwm.lazycat.utility.IoUtil;
import xyz.lwm.lazycat.utility.exception.LazycatException;
import xyz.lwm.lazycat.utility.reflect.ClassUtil;
import xyz.lwm.lazycat.utility.reflect.ReflectUtil;

import javax.annotation.PreDestroy;
import javax.sql.DataSource;

/**
 * datasource configuration
 *
 * @author lwm
 */
@Slf4j
@Configuration
public class DatasourceConfiguration {

    private static final String DATASOURCE_SERVICE_NAME = "lazycat.datasource";

    @Inject
    private DataSource datasource;

    @Bean
    @SettingPrefix(DATASOURCE_SERVICE_NAME)
    public DatasourceProperties datasourceProperties() {
        return new DatasourceProperties();
    }

    @Bean
    @ConditionalOnMissingBean
    public DataSource datasource(DatasourceProperties datasourceProperties) {
        try {

            log.info("datasource provider: {}", datasourceProperties.getDatasourceProvider());
            log.info("datasource url: {}", datasourceProperties.getUrl());

            String datasourceProvider = datasourceProperties.getDatasourceProvider();

            Class<?> clz = ClassUtil.getDefaultClassLoader().loadClass(datasourceProvider);
            DatasourceProvider provider = (DatasourceProvider) ReflectUtil.newInstance(clz);
            DataSource datasource = provider.getDatasource(datasourceProperties);

            log.info("datasource initialized");

            return datasource;

        } catch (Exception e) {
            log.error("load datasource provider error, provider: {}",
                    datasourceProperties.getDatasourceProvider(), e);
            throw new LazycatException(e);
        }
    }

    @PreDestroy
    public void destroy() {
        IoUtil.close(datasource);
    }

}
